

<!DOCTYPE html>
<html lang="zh-CN" data-default-color-scheme=&#34;auto&#34;>



<head>
  <meta charset="UTF-8">
  <link rel="apple-touch-icon" sizes="76x76" href="/img/favicon.png">
  <link rel="icon" type="image/png" href="/img/favicon.png">
  <meta name="viewport"
        content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, shrink-to-fit=no">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  
  <meta name="theme-color" content="#2f4154">
  <meta name="description" content="">
  <meta name="author" content="caoyusang">
  <meta name="keywords" content="">
  <title>Redis基础知识 - caoyusang的科研日常</title>

  <link  rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/4.4.1/css/bootstrap.min.css" />


  <link  rel="stylesheet" href="https://cdn.staticfile.org/github-markdown-css/4.0.0/github-markdown.min.css" />
  <link  rel="stylesheet" href="/lib/hint/hint.min.css" />

  
    
    
      
      <link  rel="stylesheet" href="https://cdn.staticfile.org/highlight.js/10.0.0/styles/github-gist.min.css" />
    
  

  


<!-- 主题依赖的图标库，不要自行修改 -->

<link rel="stylesheet" href="//at.alicdn.com/t/font_1749284_ba1fz6golrf.css">



<link rel="stylesheet" href="//at.alicdn.com/t/font_1736178_kmeydafke9r.css">


<link  rel="stylesheet" href="/css/main.css" />

<!-- 自定义样式保持在最底部 -->


  <script  src="/js/utils.js" ></script>
  <script  src="/js/color-schema.js" ></script>
<meta name="generator" content="Hexo 5.2.0"></head>


<body>
  <header style="height: 70vh;">
    <nav id="navbar" class="navbar fixed-top  navbar-expand-lg navbar-dark scrolling-navbar">
  <div class="container">
    <a class="navbar-brand"
       href="/">&nbsp;<strong>caoyusang</strong>&nbsp;</a>

    <button id="navbar-toggler-btn" class="navbar-toggler" type="button" data-toggle="collapse"
            data-target="#navbarSupportedContent"
            aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <div class="animated-icon"><span></span><span></span><span></span></div>
    </button>

    <!-- Collapsible content -->
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav ml-auto text-center">
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/">
                <i class="iconfont icon-home-fill"></i>
                首页
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/archives/">
                <i class="iconfont icon-archive-fill"></i>
                归档
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/categories/">
                <i class="iconfont icon-category-fill"></i>
                分类
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/tags/">
                <i class="iconfont icon-tags-fill"></i>
                标签
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/about/">
                <i class="iconfont icon-user-fill"></i>
                关于
              </a>
            </li>
          
        
        
          <li class="nav-item" id="search-btn">
            <a class="nav-link" data-toggle="modal" data-target="#modalSearch">&nbsp;<i
                class="iconfont icon-search"></i>&nbsp;</a>
          </li>
        
        
          <li class="nav-item" id="color-toggle-btn">
            <a class="nav-link" href="javascript:">&nbsp;<i
                class="iconfont icon-dark" id="color-toggle-icon"></i>&nbsp;</a>
          </li>
        
      </ul>
    </div>
  </div>
</nav>

    <div class="banner intro-2" id="background" parallax=true
         style="background: url('/img/7.jpg') no-repeat center center;
           background-size: cover;">
      <div class="full-bg-img">
        <div class="mask flex-center" style="background-color: rgba(0, 0, 0, 0.3)">
          <div class="container page-header text-center fade-in-up">
            <span class="h2" id="subtitle">
              
            </span>

            
              <div class="mt-3">
  
  
    <span class="post-meta">
      <i class="iconfont icon-date-fill" aria-hidden="true"></i>
      <time datetime="2021-01-15 21:12" pubdate>
        2021年1月15日 晚上
      </time>
    </span>
  
</div>

<div class="mt-1">
  
    
    <span class="post-meta mr-2">
      <i class="iconfont icon-chart"></i>
      3.6k 字
    </span>
  

  
    
    <span class="post-meta mr-2">
      <i class="iconfont icon-clock-fill"></i>
      
      
      58
       分钟
    </span>
  

  
  
    
      <!-- 不蒜子统计文章PV -->
      <span id="busuanzi_container_page_pv" style="display: none">
        <i class="iconfont icon-eye" aria-hidden="true"></i>
        <span id="busuanzi_value_page_pv"></span> 次
      </span>
    
  
</div>

            
          </div>

          
        </div>
      </div>
    </div>
  </header>

  <main>
    
      

<div class="container-fluid">
  <div class="row">
    <div class="d-none d-lg-block col-lg-2"></div>
    <div class="col-lg-8 nopadding-md">
      <div class="container nopadding-md" id="board-ctn">
        <div class="py-5" id="board">
          <article class="post-content mx-auto" id="post">
            <!-- SEO header -->
            <h1 style="display: none">Redis基础知识</h1>
            
              <p class="note note-info">
                
                  本文最后更新于：2 个月前
                
              </p>
            
            <div class="markdown-body" id="post-body">
              <h1 id="Redis"><a href="#Redis" class="headerlink" title="Redis"></a>Redis</h1><h2 id="NoSQL的四大分类"><a href="#NoSQL的四大分类" class="headerlink" title="NoSQL的四大分类"></a>NoSQL的四大分类</h2><p>NoSQL = Not Only SQL，泛指非关系型数据库。</p>
<h3 id="KV键值对"><a href="#KV键值对" class="headerlink" title="KV键值对"></a>KV键值对</h3><ul>
<li>新浪(Redis)</li>
<li>美团(Redis + Tair)</li>
<li>阿里、百度(Redis + memecache)</li>
</ul>
<h3 id="文档型数据库"><a href="#文档型数据库" class="headerlink" title="文档型数据库"></a>文档型数据库</h3><ul>
<li>MongoDB —— MongoDB是一个基于分布式文件存储的数据库，C++编写，主要用来处理大量的文档。MongoDB是一个介于关系型数据库和非关系型数据库中间的产品。MongoDB是非关系型数据库中功能最丰富，最像关系型数据库的一个。</li>
<li>ConthDB</li>
</ul>
<h3 id="列存储数据库"><a href="#列存储数据库" class="headerlink" title="列存储数据库"></a>列存储数据库</h3><ul>
<li>HBase</li>
<li>分布式文件系统</li>
</ul>
<h3 id="图关系数据库"><a href="#图关系数据库" class="headerlink" title="图关系数据库"></a>图关系数据库</h3><ul>
<li>NEO4J</li>
</ul>
<h2 id="Redis-Remote-Dictionary-Server"><a href="#Redis-Remote-Dictionary-Server" class="headerlink" title="Redis(Remote Dictionary Server)"></a>Redis(Remote Dictionary Server)</h2><h3 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h3><ul>
<li>Redis（Remote Dictionary Server )，即远程字典服务，是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库，并提供多种语言的API。</li>
<li>Redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件，并且在此基础上实现了master-slave(主从)同步。</li>
<li>免费和开源，是当下最热门的NoSQL技术之一，也被人们称之为结构化数据库。</li>
</ul>
<h3 id="用途"><a href="#用途" class="headerlink" title="用途"></a>用途</h3><p>Redis可用作<code>数据库、缓存和消息中间件MQ</code>。具体用途如下：</p>
<ul>
<li>内存存储并持久化（RDB和AOF）</li>
<li>效率高，可用于高速缓存</li>
<li>发布订阅系统</li>
<li>地图信息分析</li>
<li>计时器，计数器（如记录浏览量）</li>
</ul>
<h3 id="特性"><a href="#特性" class="headerlink" title="特性"></a>特性</h3><p>Redis官方推荐在Linux服务器上搭建。</p>
<p>Redis是<code>单线程</code>的，它很快，<code>基于内存操作</code>。</p>
<p>CPU不是Redis的性能瓶颈，Redis的瓶颈是机器的内存和网络带宽。</p>
<ul>
<li>多样的数据类型</li>
<li>持久化</li>
<li>集群</li>
<li>事务</li>
</ul>
<p><code>为什么Redis采用单线程还这么快？</code></p>
<p>Redis是<code>将所有的数据全部放到内存</code>中的，所以说使用单线程去操作效率就是最高的，多线程（CPU上下文会切换：耗时的操作），对于内存系统来说，如果没有上下文切换效率就是最高的。多次读写都是在一个CPU上的，在内存情况下，这个就是最佳的方案。</p>
<h2 id="Redis的安装"><a href="#Redis的安装" class="headerlink" title="Redis的安装"></a>Redis的安装</h2><p><a target="_blank" rel="noopener" href="https://www.runoob.com/redis/redis-install.html">Redis安装(菜鸟教程)</a></p>
<h2 id="客户端连接Redis"><a href="#客户端连接Redis" class="headerlink" title="客户端连接Redis"></a>客户端连接Redis</h2><pre><code class="hljs shell">redis-cli.exe -h 127.0.0.1 -p 6379</code></pre>
<h2 id="Redis压力测试"><a href="#Redis压力测试" class="headerlink" title="Redis压力测试"></a>Redis压力测试</h2><p>100000个写入请求，100个并发客户端</p>
<pre><code class="hljs shell">redis-benchmark -h localhost -p 6379 -c 100 -n 100000</code></pre>
<h2 id="Redis基本知识"><a href="#Redis基本知识" class="headerlink" title="Redis基本知识"></a>Redis基本知识</h2><p>Redis有16个数据库，默认使用第0个，可以使用select进行切换。</p>
<p><code>基本指令</code></p>
<div class="table-container">
<table>
<thead>
<tr>
<th style="text-align:center">指令</th>
<th style="text-align:center">作用</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">keys *</td>
<td style="text-align:center">查看数据库所有的key</td>
</tr>
<tr>
<td style="text-align:center">flushdb</td>
<td style="text-align:center">清空当前数据库</td>
</tr>
<tr>
<td style="text-align:center">flushall</td>
<td style="text-align:center">清空所有数据库</td>
</tr>
<tr>
<td style="text-align:center">set [key] [value]</td>
<td style="text-align:center">设置键值对，重复设置一个键会将原来的值给覆盖掉</td>
</tr>
<tr>
<td style="text-align:center">get [key]</td>
<td style="text-align:center">通过键名获取值</td>
</tr>
<tr>
<td style="text-align:center">EXISTS [key]</td>
<td style="text-align:center">检查键是否存在</td>
</tr>
<tr>
<td style="text-align:center">move [key] [0-15]</td>
<td style="text-align:center">将键移动到某个数据库</td>
</tr>
<tr>
<td style="text-align:center">expire [key] [time]</td>
<td style="text-align:center">将键设置为n秒后过期</td>
</tr>
<tr>
<td style="text-align:center">ttl [key]</td>
<td style="text-align:center">查看键剩余存活时间</td>
</tr>
<tr>
<td style="text-align:center">type [key]</td>
<td style="text-align:center">查看键类型</td>
</tr>
</tbody>
</table>
</div>
<h2 id="Redis的五大数据类型"><a href="#Redis的五大数据类型" class="headerlink" title="Redis的五大数据类型"></a>Redis的五大数据类型</h2><h3 id="String"><a href="#String" class="headerlink" title="String"></a>String</h3><p>ps：value除了字符串还可以是数字</p>
<p><code>使用场景</code></p>
<ul>
<li>计数器</li>
<li>统计多单位的数目</li>
<li>对象缓存存储</li>
</ul>
<div class="table-container">
<table>
<thead>
<tr>
<th style="text-align:center">指令</th>
<th style="text-align:center">作用</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center"><code>append [key] [value]</code></td>
<td style="text-align:center">在键上追加值，若此键不存在，相当于set命令</td>
</tr>
<tr>
<td style="text-align:center"><code>strlen [key]</code></td>
<td style="text-align:center"><code>获取键的值的长度</code></td>
</tr>
<tr>
<td style="text-align:center"><code>incr [key]</code></td>
<td style="text-align:center">键的值加1</td>
</tr>
<tr>
<td style="text-align:center"><code>decr [key]</code></td>
<td style="text-align:center">键的值减1</td>
</tr>
<tr>
<td style="text-align:center"><code>incrby [key] [step]</code></td>
<td style="text-align:center">键的值加n</td>
</tr>
<tr>
<td style="text-align:center"><code>decrby [key] [step]</code></td>
<td style="text-align:center">键的值减n</td>
</tr>
<tr>
<td style="text-align:center"><code>getrange [key] [start] [end]</code></td>
<td style="text-align:center"><code>截取字符串。getrange [key] 0 -1 等同get命令</code></td>
</tr>
<tr>
<td style="text-align:center"><code>setrange [key] [location] [value]</code></td>
<td style="text-align:center">从指定位置开始替换</td>
</tr>
<tr>
<td style="text-align:center"><code>setex [key] [time] [value]</code></td>
<td style="text-align:center">可理解为set和expire连用</td>
</tr>
<tr>
<td style="text-align:center"><code>setnx [key] [value]</code></td>
<td style="text-align:center">若键不存在，创建并设置值（分布式锁中常用）</td>
</tr>
<tr>
<td style="text-align:center"><code>mset [key1] [value1] [key2] [value2]......</code></td>
<td style="text-align:center"><code>批量设置</code></td>
</tr>
<tr>
<td style="text-align:center"><code>mget[key1] [key2]......</code></td>
<td style="text-align:center"><code>批量取值</code></td>
</tr>
<tr>
<td style="text-align:center"><code>msetnx [key1] [value1] [key2] [value2]......</code></td>
<td style="text-align:center">若键不存在，创建并设置值（批量），具有原子性（若其中一个设置失败则整体失败）</td>
</tr>
<tr>
<td style="text-align:center"><code>getset [key] [value]</code></td>
<td style="text-align:center"><code>先get，返回get到的值，将value覆盖原有值</code></td>
</tr>
</tbody>
</table>
</div>
<h3 id="List"><a href="#List" class="headerlink" title="List"></a>List</h3><p><code>特点</code></p>
<ul>
<li>值有序</li>
<li>可重</li>
<li>指令首的”l”含义：除了push和pop操作代表头尾的意思，其他都是list的意思</li>
</ul>
<div class="table-container">
<table>
<thead>
<tr>
<th style="text-align:center">指令</th>
<th style="text-align:center">作用</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center"><code>lpush [listname] [value]</code></td>
<td style="text-align:center">往列表头部插入数据</td>
</tr>
<tr>
<td style="text-align:center"><code>lrange [listname] [range(0 1)]</code></td>
<td style="text-align:center"><code>获取列表中某个范围的值（获取列表中第0和第1个值）</code></td>
</tr>
<tr>
<td style="text-align:center"><code>rpush [listname] [value]</code></td>
<td style="text-align:center">往列表尾部插入数据</td>
</tr>
<tr>
<td style="text-align:center"><code>lpop [listname]</code></td>
<td style="text-align:center">移除列表头元素</td>
</tr>
<tr>
<td style="text-align:center"><code>rpop [listname]</code></td>
<td style="text-align:center">移除列表尾元素</td>
</tr>
<tr>
<td style="text-align:center"><code>lindex [listname] [index]</code></td>
<td style="text-align:center"><code>通过下标获取值</code></td>
</tr>
<tr>
<td style="text-align:center"><code>llen [listname]</code></td>
<td style="text-align:center"><code>获取列表长度</code></td>
</tr>
<tr>
<td style="text-align:center"><code>lrem [listname] [count] [value]</code></td>
<td style="text-align:center">移除n个重复的指定值</td>
</tr>
<tr>
<td style="text-align:center"><code>ltrim [listname] [range(1 2)]</code></td>
<td style="text-align:center"><code>截取范围内值（截取列表中第1和第2个值）（注：原list将被改变，未被截取到的数据将被删除）</code></td>
</tr>
<tr>
<td style="text-align:center"><code>rpoplpush [source] [destination]</code></td>
<td style="text-align:center">移除列表的最后一个元素并将其插入另一个列表的头部</td>
</tr>
<tr>
<td style="text-align:center"><code>lset [listname] [index] [value]</code></td>
<td style="text-align:center"><code>修改下标值</code></td>
</tr>
<tr>
<td style="text-align:center"><code>exist [listname]</code></td>
<td style="text-align:center"><code>判断某列表是否存在</code></td>
</tr>
<tr>
<td style="text-align:center">`linsert [listname] [before</td>
<td style="text-align:center">after] [value] [value]`</td>
<td><code>在某个值的前面/后面插入值</code></td>
</tr>
</tbody>
</table>
</div>
<p><code>底层实现</code>：快速链表</p>
<p><code>使用场景</code>：消息队列、栈</p>
<h3 id="Set"><a href="#Set" class="headerlink" title="Set"></a>Set</h3><p><code>特点</code></p>
<ul>
<li>值无序</li>
<li>不可重复</li>
<li>指令首”s”的含义：代表set</li>
</ul>
<div class="table-container">
<table>
<thead>
<tr>
<th style="text-align:center">指令</th>
<th style="text-align:center">作用</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center"><code>sadd [setname] [value]</code></td>
<td style="text-align:center">往集合中添加值</td>
</tr>
<tr>
<td style="text-align:center"><code>smembers [setname]</code></td>
<td style="text-align:center">查看某集合</td>
</tr>
<tr>
<td style="text-align:center"><code>sismember [setname] [value]</code></td>
<td style="text-align:center"><code>判断集合中是否存在该值</code>（返回0表示不存在，返回1表示存在）</td>
</tr>
<tr>
<td style="text-align:center"><code>scard [setname]</code></td>
<td style="text-align:center"><code>获取集合元素个数</code></td>
</tr>
<tr>
<td style="text-align:center"><code>srem [setname] [value]</code></td>
<td style="text-align:center">移除集合中的指定元素</td>
</tr>
<tr>
<td style="text-align:center"><code>srandmember [setname]</code></td>
<td style="text-align:center">随机取出一个元素</td>
</tr>
<tr>
<td style="text-align:center"><code>srandmember [setname] [count]</code></td>
<td style="text-align:center"><code>随机取出若干个元</code></td>
</tr>
<tr>
<td style="text-align:center"><code>spop [setname]</code></td>
<td style="text-align:center">移除一个元素</td>
</tr>
<tr>
<td style="text-align:center"><code>smove [source] [destination] [value]</code></td>
<td style="text-align:center"><code>移除列表的一个指定元素并将其添加到另一个集合</code></td>
</tr>
<tr>
<td style="text-align:center"><code>diff [set1] [set2]</code></td>
<td style="text-align:center">找出属于set1但不属于set2的元素（<code>求差集</code>）</td>
</tr>
<tr>
<td style="text-align:center"><code>sinter [set1] [set2]</code></td>
<td style="text-align:center"><code>求交集</code></td>
</tr>
<tr>
<td style="text-align:center"><code>sunion [set1] [set2]</code></td>
<td style="text-align:center"><code>求并集</code></td>
</tr>
</tbody>
</table>
</div>
<p><code>使用场景</code></p>
<ul>
<li>集合操作(交、并、差)</li>
</ul>
<h3 id="Hash"><a href="#Hash" class="headerlink" title="Hash"></a>Hash</h3><p><code>使用场景</code></p>
<ul>
<li>对象存储</li>
<li>经常变更的K-V数据，例如用户信息</li>
</ul>
<div class="table-container">
<table>
<thead>
<tr>
<th style="text-align:center">指令</th>
<th style="text-align:center">作用</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center"><code>hset [hashname] [key] [value]</code></td>
<td style="text-align:center">存键值对</td>
</tr>
<tr>
<td style="text-align:center"><code>hget [hashname] [key]</code></td>
<td style="text-align:center">由键取值</td>
</tr>
<tr>
<td style="text-align:center"><code>hmset [hashname] [key1] [value1] [key2][value2]......</code></td>
<td style="text-align:center">批量存键值对</td>
</tr>
<tr>
<td style="text-align:center"><code>hmget [hashname] [key1] [key2]......</code></td>
<td style="text-align:center">根据键批量取值</td>
</tr>
<tr>
<td style="text-align:center"><code>hgetall [hashname]</code></td>
<td style="text-align:center"><code>获取所有键值对</code></td>
</tr>
<tr>
<td style="text-align:center"><code>hdel [hashname] [key]</code></td>
<td style="text-align:center"><code>删除指定键值对</code></td>
</tr>
<tr>
<td style="text-align:center"><code>hlen [hashname]</code></td>
<td style="text-align:center"><code>获取哈希表长度（即有几个键值对）</code></td>
</tr>
<tr>
<td style="text-align:center"><code>hexist [hashname] [key]</code></td>
<td style="text-align:center">判断表中键值对是否存在（返回0表示不存在，返回1表示存在）</td>
</tr>
<tr>
<td style="text-align:center"><code>hkeys [hashname]</code></td>
<td style="text-align:center"><code>获取表中所有的key</code></td>
</tr>
<tr>
<td style="text-align:center"><code>hvals [hashname]</code></td>
<td style="text-align:center"><code>获取表中所有的value</code></td>
</tr>
<tr>
<td style="text-align:center"><code>hincrby [hashname] [key] [increase]</code></td>
<td style="text-align:center">将key对应的value增加若干大小（可通过负数实现减少）</td>
</tr>
<tr>
<td style="text-align:center"><code>hsetnx [hashname] [key] [value]</code></td>
<td style="text-align:center"><code>若键不存在，创建并设置值</code></td>
</tr>
</tbody>
</table>
</div>
<h3 id="Zset"><a href="#Zset" class="headerlink" title="Zset"></a>Zset</h3><p><code>特点</code></p>
<ul>
<li>在set基础上增加排序权重</li>
<li>有序集合</li>
</ul>
<div class="table-container">
<table>
<thead>
<tr>
<th style="text-align:center">指令</th>
<th style="text-align:center">作用</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center"><code>zadd [setname] [score] [value]</code></td>
<td style="text-align:center">往集合中添加值</td>
</tr>
<tr>
<td style="text-align:center"><code>zrange [setname] [range(0 1)]</code></td>
<td style="text-align:center">获取集合中某个范围的值（获取集合中第0和第1个值）</td>
</tr>
<tr>
<td style="text-align:center"><code>zrangebyscore [setname] -inf +inf</code></td>
<td style="text-align:center"><code>按分数从小到大获取集合中的值</code></td>
</tr>
<tr>
<td style="text-align:center"><code>zrevrangebyscore [setname] +inf -inf</code></td>
<td style="text-align:center"><code>按分数从大到小获取集合中的值</code></td>
</tr>
<tr>
<td style="text-align:center"><code>zrangebyscore [setname] -inf +inf withscores</code></td>
<td style="text-align:center"><code>按分数从小到大获取集合中的值并显示分数</code></td>
</tr>
<tr>
<td style="text-align:center"><code>zrem [setname] [value]</code></td>
<td style="text-align:center">移除集合中的指定元素</td>
</tr>
<tr>
<td style="text-align:center"><code>zcard [setname]</code></td>
<td style="text-align:center"><code>获取集合元素个数</code></td>
</tr>
<tr>
<td style="text-align:center"><code>zcount [setname] [scorerange(1 3)]</code></td>
<td style="text-align:center"><code>某分数范围内的值的个数（分数在[1,3]范围内的值的个数）</code></td>
</tr>
</tbody>
</table>
</div>
<h2 id="Redis三种特殊数据类型"><a href="#Redis三种特殊数据类型" class="headerlink" title="Redis三种特殊数据类型"></a>Redis三种特殊数据类型</h2><h3 id="geospatial"><a href="#geospatial" class="headerlink" title="geospatial"></a>geospatial</h3><p>底层基于<code>Zset</code></p>
<div class="table-container">
<table>
<thead>
<tr>
<th style="text-align:center">指令</th>
<th style="text-align:center">作用</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center"><code>geoadd [key] [longitude] [latitude] [cityname]</code></td>
<td style="text-align:center"><code>添加地理位置（经纬度）</code></td>
</tr>
<tr>
<td style="text-align:center"><code>geopos [key] [cityname]</code></td>
<td style="text-align:center"><code>获取指定城市的地理位置</code></td>
</tr>
<tr>
<td style="text-align:center"><code>geodist [key] [cityname1] [cityname2] [unit]</code></td>
<td style="text-align:center"><code>查询两地的直线距离（默认单位为米）</code></td>
</tr>
<tr>
<td style="text-align:center"><code>georadius [key] [longitude] [latitude] [radius] [unit] [count]</code></td>
<td style="text-align:center">以某处为中心查询其方圆若干（单位）的城市（可限制显示数量）</td>
</tr>
<tr>
<td style="text-align:center"><code>georadius [key] [longitude] [latitude] [radius] [unit]    withdist [count]</code></td>
<td style="text-align:center">以某处为中心查询其方圆若干（单位）的城市（带直线距离）</td>
</tr>
<tr>
<td style="text-align:center"><code>georadius [key] [longitude] [latitude] [radius] [unit]    withcoord    [count]</code></td>
<td style="text-align:center">以某处为中心查询其方圆若干（单位）的城市（带经纬度）</td>
</tr>
<tr>
<td style="text-align:center"><code>georadiusbymember [key] [cityname] [radius] [unit]</code></td>
<td style="text-align:center">以某城市为中心查询其方圆若干（单位）的城市</td>
</tr>
<tr>
<td style="text-align:center"><code>geohash [key] [cityname]</code></td>
<td style="text-align:center">返回城市的哈希值（二维的经纬度转换成一维的字符串，两个字符串显示越靠近说明两地距离越接近）</td>
</tr>
</tbody>
</table>
</div>
<h3 id="Hyperloglog"><a href="#Hyperloglog" class="headerlink" title="Hyperloglog"></a>Hyperloglog</h3><p><code>概述</code></p>
<p>它是用作基数统计的算法。基数计算（cardinality counting）指的是统计一批数据中的不重复元素的个数。</p>
<p><code>应用场景</code></p>
<ul>
<li>网页的UV（用户访问量），同一个人访问网站多次，视为一次访问</li>
</ul>
<p><code>优点</code></p>
<p>占用的内存是固定的，264个不同元素的数据，只需要废12KB内存。所以如果要从内存角度来比较的话，Hyperloglog是首选。</p>
<p><code>缺点</code></p>
<p>具有0.81%的错误率</p>
<div class="table-container">
<table>
<thead>
<tr>
<th style="text-align:center">指令</th>
<th style="text-align:center">作用</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center"><code>pfadd [key] [value1] [value2]......</code></td>
<td style="text-align:center">存放数据</td>
</tr>
<tr>
<td style="text-align:center"><code>pfcount [key]</code></td>
<td style="text-align:center"><code>统计元素数量</code></td>
</tr>
<tr>
<td style="text-align:center"><code>pfmerge [newkey] [key1] [key2]......</code></td>
<td style="text-align:center"><code>合并若干key到一个新的key</code></td>
</tr>
</tbody>
</table>
</div>
<h3 id="Bitmap"><a href="#Bitmap" class="headerlink" title="Bitmap"></a>Bitmap</h3><p><code>概述</code></p>
<p>位图，即位存储，操作二进制位来进行记录，只有0和1两个状态。</p>
<p><code>应用场景</code></p>
<p>用户状态统计。用户活跃度，登录状态，打卡记录。拥有两个状态的用户信息的存储都可以用Bitmap。</p>
<div class="table-container">
<table>
<thead>
<tr>
<th style="text-align:center">指令</th>
<th style="text-align:center">作用</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center"><code>setbit [key] [offset] [value]</code></td>
<td style="text-align:center">存值</td>
</tr>
<tr>
<td style="text-align:center"><code>getbit [key] [offset]</code></td>
<td style="text-align:center">取值</td>
</tr>
<tr>
<td style="text-align:center"><code>bitcount [key]</code></td>
<td style="text-align:center"><code>统计1的个数</code></td>
</tr>
</tbody>
</table>
</div>
<h2 id="Redis基本事务操作"><a href="#Redis基本事务操作" class="headerlink" title="Redis基本事务操作"></a>Redis基本事务操作</h2><p><strong>Redis单条命令是保证原子性的，但是它的事务不保证原子性！</strong></p>
<p><code>Redis事务本质</code></p>
<p>一组命令的集合！一个事务中的所有命令都会被序列化，在事务执行过程中，会按照一次性、顺序性、排他性等原则执行一系列的命令！</p>
<p><strong>Redis事务没有隔离级别的概念！</strong></p>
<p>所有的命令在事务中，并没有直接被执行！只有发起执行命令的时候才会执行！<strong>Exec</strong></p>
<p><code>事务</code></p>
<ul>
<li>开启事务 —— multi</li>
<li>命令入队 —— 一系列命令</li>
<li>执行事务 —— exec</li>
<li>放弃事务 —— discard</li>
</ul>
<p><code>异常</code></p>
<ul>
<li>编译型异常 —— 命令使用错误，事务中其他命令都不会被执行</li>
<li>运行时异常 —— 命令没有语法错误，但是运行时产生错误，除了报错的命令外，事务中其他命令依然会被执行</li>
</ul>
<h2 id="Redis监控——悲观锁和乐观锁"><a href="#Redis监控——悲观锁和乐观锁" class="headerlink" title="Redis监控——悲观锁和乐观锁"></a>Redis监控——悲观锁和乐观锁</h2><p><code>悲观锁</code> —— 认为什么时候都可能出现问题，因此无论做什么都加锁</p>
<p><code>乐观锁(常用)</code> —— 认为什么时候不会出现问题，不会对任何操作上锁。只会更新数据的时候去判断一下，在此期间是否有人修改过这个数据，步骤如下：</p>
<ul>
<li>获取version （<code>watch</code> data）</li>
<li>更新时比对version，若version发生变动，则告诉事务，事务执行失败，执行失败后先<code>unwatch data</code>，再<code>watch data</code>更新version</li>
</ul>
<h2 id="Jedis-——-Java连接开发工具"><a href="#Jedis-——-Java连接开发工具" class="headerlink" title="Jedis —— Java连接开发工具"></a>Jedis —— Java连接开发工具</h2><h3 id="连接"><a href="#连接" class="headerlink" title="连接"></a>连接</h3><h4 id="1-导入包"><a href="#1-导入包" class="headerlink" title="1. 导入包"></a>1. 导入包</h4><pre><code class="hljs xml"><span class="hljs-comment">&lt;!-- https://mvnrepository.com/artifact/redis.clients/jedis --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>redis.clients<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>jedis<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>3.5.1<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>com.alibaba<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>fastjson<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>1.2.73<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span></code></pre>
<h4 id="2-连接Redis"><a href="#2-连接Redis" class="headerlink" title="2.连接Redis"></a>2.连接Redis</h4><pre><code class="hljs java"><span class="hljs-keyword">package</span> com.youzikeji.redis;

<span class="hljs-keyword">import</span> redis.clients.jedis.Jedis;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TestJedis</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>&#123;
        Jedis jedis = <span class="hljs-keyword">new</span> Jedis(<span class="hljs-string">&quot;127.0.0.1&quot;</span>, <span class="hljs-number">6379</span>);
        System.out.println(jedis.ping());
    &#125;
&#125;
</code></pre>
<h4 id="3-关闭连接"><a href="#3-关闭连接" class="headerlink" title="3.关闭连接"></a>3.关闭连接</h4><pre><code class="hljs java">jedis.close();</code></pre>
<h3 id="事务"><a href="#事务" class="headerlink" title="事务"></a>事务</h3><pre><code class="hljs java"><span class="hljs-keyword">package</span> com.youzikeji.redis;

<span class="hljs-keyword">import</span> com.alibaba.fastjson.JSONObject;
<span class="hljs-keyword">import</span> redis.clients.jedis.Jedis;
<span class="hljs-keyword">import</span> redis.clients.jedis.Transaction;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TestTransaction</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>&#123;
        Jedis jedis = <span class="hljs-keyword">new</span> Jedis(<span class="hljs-string">&quot;127.0.0.1&quot;</span>, <span class="hljs-number">6379</span>);
        jedis.flushDB();
        JSONObject jsonObject = <span class="hljs-keyword">new</span> JSONObject();
        jsonObject.put(<span class="hljs-string">&quot;name&quot;</span>, <span class="hljs-string">&quot;caoyusang&quot;</span>);
        jsonObject.put(<span class="hljs-string">&quot;age&quot;</span>, <span class="hljs-number">23</span>);
        String result = jsonObject.toString();
        System.out.println(result);
        <span class="hljs-comment">// 开启事务</span>
        Transaction multi = jedis.multi();
        <span class="hljs-comment">// jedis.watch(result); // 开启监控——乐观锁</span>
        <span class="hljs-keyword">try</span> &#123;
            multi.set(<span class="hljs-string">&quot;user1&quot;</span>, result);
            multi.lpush(<span class="hljs-string">&quot;list&quot;</span>,result);
<span class="hljs-comment">//            int i= 1 / 0;  // 代码出现异常，执行失败！</span>
            multi.exec();   <span class="hljs-comment">// 执行事务</span>
        &#125; <span class="hljs-keyword">catch</span> (Exception e) &#123;
            multi.discard();    <span class="hljs-comment">// 放弃事务</span>
        &#125; <span class="hljs-keyword">finally</span> &#123;
            System.out.println(jedis.get(<span class="hljs-string">&quot;user1&quot;</span>));
            System.out.println(jedis.lpop(<span class="hljs-string">&quot;list&quot;</span>));
            jedis.close();  <span class="hljs-comment">// 关闭连接</span>
        &#125;
    &#125;
&#125;</code></pre>
<h2 id="SpringBoot整合Redis"><a href="#SpringBoot整合Redis" class="headerlink" title="SpringBoot整合Redis"></a>SpringBoot整合Redis</h2><h3 id="简介-1"><a href="#简介-1" class="headerlink" title="简介"></a>简介</h3><p>SpringBoot操作数据：spring-data (jpa jdbc mongodb redis elasticsearch)！</p>
<p>SpringBoot2.x之后，原来使用的Jedis被替换为了lettuce。</p>
<p><code>Jedis</code>：采用的直连，多个线程操作的话，是不安全的，如果想要避免不安全的，使用jedis pool 连接池！ 更像 BIO 模式</p>
<p><code>lettuce</code>： 采用netty，实例可以再多个线程中进行共享，不存在线程不安全的情况！可以减少线程数据了，更像NIO模式</p>
<h3 id="源码分析"><a href="#源码分析" class="headerlink" title="源码分析"></a>源码分析</h3><pre><code class="hljs java"><span class="hljs-meta">@Bean</span>
<span class="hljs-meta">@ConditionalOnMissingBean(</span>
<span class="hljs-meta">    name = &#123;&quot;redisTemplate&quot;&#125;</span>
<span class="hljs-meta">)</span>    <span class="hljs-comment">// 我们可以自己定义一个redisTemplate来替换这个默认的！</span>
<span class="hljs-meta">@ConditionalOnSingleCandidate(RedisConnectionFactory.class)</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> RedisTemplate&lt;Object, Object&gt; <span class="hljs-title">redisTemplate</span><span class="hljs-params">(RedisConnectionFactory redisConnectionFactory)</span> </span>&#123;
    <span class="hljs-comment">// 默认的RedisTemplate 没有过多的设置，redis对象都是需要序列化的！</span>
    <span class="hljs-comment">// 两个泛型都是object，object的类型，我们后续使用需要强制转换成&lt;String,object&gt;</span>
    RedisTemplate&lt;Object, Object&gt; template = <span class="hljs-keyword">new</span> RedisTemplate();
    template.setConnectionFactory(redisConnectionFactory);
    <span class="hljs-keyword">return</span> template;
&#125;
<span class="hljs-meta">@Bean</span>
<span class="hljs-meta">@ConditionalOnMissingBean</span>    <span class="hljs-comment">// 由于String 是redis中最常使用的类型，所以说单独提出来了一个bean！</span>
<span class="hljs-meta">@ConditionalOnSingleCandidate(RedisConnectionFactory.class)</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> StringRedisTemplate <span class="hljs-title">stringRedisTemplate</span><span class="hljs-params">(RedisConnectionFactory redisConnectionFactory)</span> </span>&#123;
    StringRedisTemplate template = <span class="hljs-keyword">new</span> StringRedisTemplate();
    template.setConnectionFactory(redisConnectionFactory);
    <span class="hljs-keyword">return</span> template;
&#125;</code></pre>
<h3 id="依赖导入"><a href="#依赖导入" class="headerlink" title="依赖导入"></a>依赖导入</h3><pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.boot<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-boot-starter-data-redis<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span></code></pre>
<h3 id="配置连接"><a href="#配置连接" class="headerlink" title="配置连接"></a>配置连接</h3><pre><code class="hljs properties"><span class="hljs-meta">spring.redis.host</span>=<span class="hljs-string">127.0.0.1</span>
<span class="hljs-meta">spring.redis.port</span>=<span class="hljs-string">6379</span></code></pre>
<h3 id="自定义RedisTemplate"><a href="#自定义RedisTemplate" class="headerlink" title="自定义RedisTemplate"></a>自定义RedisTemplate</h3><pre><code class="hljs java"><span class="hljs-keyword">package</span> com.youzikeji.config;

<span class="hljs-keyword">import</span> com.fasterxml.jackson.annotation.JsonAutoDetect;
<span class="hljs-keyword">import</span> com.fasterxml.jackson.annotation.JsonTypeInfo;
<span class="hljs-keyword">import</span> com.fasterxml.jackson.annotation.PropertyAccessor;
<span class="hljs-keyword">import</span> com.fasterxml.jackson.databind.ObjectMapper;
<span class="hljs-keyword">import</span> com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
<span class="hljs-keyword">import</span> org.springframework.context.annotation.Bean;
<span class="hljs-keyword">import</span> org.springframework.context.annotation.Configuration;
<span class="hljs-keyword">import</span> org.springframework.data.redis.connection.RedisConnectionFactory;
<span class="hljs-keyword">import</span> org.springframework.data.redis.core.RedisTemplate;
<span class="hljs-keyword">import</span> org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
<span class="hljs-keyword">import</span> org.springframework.data.redis.serializer.StringRedisSerializer;

<span class="hljs-meta">@Configuration</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">RedisConfig</span> </span>&#123;
    <span class="hljs-meta">@Bean</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> RedisTemplate&lt;String,Object&gt; <span class="hljs-title">redisTemplate</span><span class="hljs-params">(RedisConnectionFactory factory)</span></span>&#123;
        <span class="hljs-comment">// 为了自己开发方便，一般直接使用&lt;String,Object&gt;</span>
        RedisTemplate&lt;String, Object&gt; template = <span class="hljs-keyword">new</span> RedisTemplate&lt;&gt;();
        template.setConnectionFactory(factory);
        <span class="hljs-comment">// Json序列化配置</span>
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = <span class="hljs-keyword">new</span> Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = <span class="hljs-keyword">new</span> ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        <span class="hljs-comment">// om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);</span>
        om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.WRAPPER_ARRAY);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        <span class="hljs-comment">// String的序列化</span>
        StringRedisSerializer stringRedisSerializer = <span class="hljs-keyword">new</span> StringRedisSerializer();
        <span class="hljs-comment">// key采用String的序列化方式</span>
        template.setKeySerializer(stringRedisSerializer);
        <span class="hljs-comment">// hash的key也采用String的序列化方式</span>
        template.setHashKeySerializer(stringRedisSerializer);
        <span class="hljs-comment">// value序列化方式采用jackson</span>
        template.setValueSerializer(jackson2JsonRedisSerializer);
        <span class="hljs-comment">// hash的value序列化方式采用jackson</span>
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();
        <span class="hljs-keyword">return</span> template;
    &#125;
&#125;
</code></pre>
<h3 id="测试"><a href="#测试" class="headerlink" title="测试"></a>测试</h3><pre><code class="hljs java"><span class="hljs-keyword">package</span> com.youzikeji;

<span class="hljs-keyword">import</span> org.junit.jupiter.api.Test;
<span class="hljs-keyword">import</span> org.springframework.beans.factory.annotation.Autowired;
<span class="hljs-keyword">import</span> org.springframework.beans.factory.annotation.Qualifier;
<span class="hljs-keyword">import</span> org.springframework.boot.test.context.SpringBootTest;
<span class="hljs-keyword">import</span> org.springframework.data.redis.core.RedisTemplate;

<span class="hljs-meta">@SpringBootTest</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SpringbootApplicationTests</span> </span>&#123;

    <span class="hljs-meta">@Autowired</span>
    <span class="hljs-meta">@Qualifier(&quot;redisTemplate&quot;)</span>
    <span class="hljs-keyword">private</span> RedisTemplate redisTemplate;
    <span class="hljs-comment">// redisTemplate 操作不同的数据类型，api和我们的命令一样</span>
    <span class="hljs-comment">// opsForValue 操作字符串 类似 String</span>
    <span class="hljs-comment">// opsForList 操作list 类似list</span>
    <span class="hljs-comment">// 。。。依此类推</span>
    <span class="hljs-comment">// 除了基本的操作，我们常用的方法都可以直接通过redisTemplate操作，比如事务和基本的crud</span>
    <span class="hljs-comment">// 获取redis 的连接对象</span>
    <span class="hljs-comment">// RedisConnection connection = redisTemplate.getConnectionFactory().getConnection();</span>
    <span class="hljs-comment">// connection.flushAll();</span>
    <span class="hljs-comment">// connection.flushDb();</span>
    <span class="hljs-meta">@Test</span>
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">contextLoads</span><span class="hljs-params">()</span> </span>&#123;
        redisTemplate.opsForValue().set(<span class="hljs-string">&quot;name&quot;</span>, <span class="hljs-string">&quot;caoyusang&quot;</span>);
        System.out.println(redisTemplate.opsForValue().get(<span class="hljs-string">&quot;name&quot;</span>));
    &#125;

&#125;
</code></pre>

            </div>
            <hr>
            <div>
              <div class="post-metas mb-3">
                
                  <div class="post-meta mr-3">
                    <i class="iconfont icon-category"></i>
                    
                      <a class="hover-with-bg" href="/categories/%E6%95%B0%E6%8D%AE%E5%BA%93/">数据库</a>
                    
                  </div>
                
                
                  <div class="post-meta">
                    <i class="iconfont icon-tags"></i>
                    
                      <a class="hover-with-bg" href="/tags/Redis/">Redis</a>
                    
                  </div>
                
              </div>
              
                <p class="note note-warning">本博客所有文章除特别声明外，均采用 <a target="_blank" href="https://creativecommons.org/licenses/by-sa/4.0/deed.zh" rel="nofollow noopener noopener">CC BY-SA 4.0 协议</a> ，转载请注明出处！</p>
              
              
                <div class="post-prevnext row">
                  <article class="post-prev col-6">
                    
                    
                      <a href="/2021/01/18/leetcode%E9%A2%98%E8%A7%A3%E4%B9%8B%E4%BA%8C%E5%8F%89%E6%A0%91/">
                        <i class="iconfont icon-arrowleft"></i>
                        <span class="hidden-mobile">leetcode题解之二叉树</span>
                        <span class="visible-mobile">上一篇</span>
                      </a>
                    
                  </article>
                  <article class="post-next col-6">
                    
                    
                      <a href="/2021/01/05/Spring%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/">
                        <span class="hidden-mobile">Spring基础知识</span>
                        <span class="visible-mobile">下一篇</span>
                        <i class="iconfont icon-arrowright"></i>
                      </a>
                    
                  </article>
                </div>
              
            </div>

            
          </article>
        </div>
      </div>
    </div>
    
      <div class="d-none d-lg-block col-lg-2 toc-container" id="toc-ctn">
        <div id="toc">
  <p class="toc-header"><i class="iconfont icon-list"></i>&nbsp;目录</p>
  <div id="tocbot"></div>
</div>

      </div>
    
  </div>
</div>

<!-- Custom -->


    
  </main>

  
    <a id="scroll-top-button" href="#" role="button">
      <i class="iconfont icon-arrowup" aria-hidden="true"></i>
    </a>
  

  
    <div class="modal fade" id="modalSearch" tabindex="-1" role="dialog" aria-labelledby="ModalLabel"
     aria-hidden="true">
  <div class="modal-dialog modal-dialog-scrollable modal-lg" role="document">
    <div class="modal-content">
      <div class="modal-header text-center">
        <h4 class="modal-title w-100 font-weight-bold">搜索</h4>
        <button type="button" id="local-search-close" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body mx-3">
        <div class="md-form mb-5">
          <input type="text" id="local-search-input" class="form-control validate">
          <label data-error="x" data-success="v"
                 for="local-search-input">关键词</label>
        </div>
        <div class="list-group" id="local-search-result"></div>
      </div>
    </div>
  </div>
</div>
  

  

  <footer class="text-center mt-5 py-3">
  <div class="footer-content">
     <a href="https://hexo.io" target="_blank" rel="nofollow noopener"><span>Hexo</span></a> <i class="iconfont icon-love"></i> <a href="https://github.com/fluid-dev/hexo-theme-fluid" target="_blank" rel="nofollow noopener"><span>Fluid</span></a> 
  </div>
  

  

  
</footer>

<!-- SCRIPTS -->
<script  src="https://cdn.staticfile.org/jquery/3.4.1/jquery.min.js" ></script>
<script  src="https://cdn.staticfile.org/twitter-bootstrap/4.4.1/js/bootstrap.min.js" ></script>
<script  src="/js/debouncer.js" ></script>
<script  src="/js/main.js" ></script>

<!-- Plugins -->


  
    <script  src="/js/lazyload.js" ></script>
  



  



  <script defer src="https://cdn.staticfile.org/clipboard.js/2.0.6/clipboard.min.js" ></script>
  <script  src="/js/clipboard-use.js" ></script>



  <script defer src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js" ></script>





  <script  src="https://cdn.staticfile.org/tocbot/4.11.1/tocbot.min.js" ></script>
  <script>
    $(document).ready(function () {
      var boardCtn = $('#board-ctn');
      var boardTop = boardCtn.offset().top;

      tocbot.init({
        tocSelector: '#tocbot',
        contentSelector: '#post-body',
        headingSelector: 'h1,h2,h3,h4,h5,h6',
        linkClass: 'tocbot-link',
        activeLinkClass: 'tocbot-active-link',
        listClass: 'tocbot-list',
        isCollapsedClass: 'tocbot-is-collapsed',
        collapsibleClass: 'tocbot-is-collapsible',
        collapseDepth: 0,
        scrollSmooth: true,
        headingsOffset: -boardTop
      });
      if ($('.toc-list-item').length > 0) {
        $('#toc').css('visibility', 'visible');
      }
    });
  </script>



  <script  src="https://cdn.staticfile.org/typed.js/2.0.11/typed.min.js" ></script>
  <script>
    var typed = new Typed('#subtitle', {
      strings: [
        '  ',
        "Redis基础知识&nbsp;",
      ],
      cursorChar: "_",
      typeSpeed: 70,
      loop: false,
    });
    typed.stop();
    $(document).ready(function () {
      $(".typed-cursor").addClass("h2");
      typed.start();
    });
  </script>



  <script  src="https://cdn.staticfile.org/anchor-js/4.2.2/anchor.min.js" ></script>
  <script>
    anchors.options = {
      placement: "right",
      visible: "hover",
      
    };
    var el = "h1,h2,h3,h4,h5,h6".split(",");
    var res = [];
    for (item of el) {
      res.push(".markdown-body > " + item)
    }
    anchors.add(res.join(", "))
  </script>



  <script  src="/js/local-search.js" ></script>
  <script>
    var path = "/local-search.xml";
    var inputArea = document.querySelector("#local-search-input");
    inputArea.onclick = function () {
      searchFunc(path, 'local-search-input', 'local-search-result');
      this.onclick = null
    }
  </script>



  <script  src="https://cdn.staticfile.org/fancybox/3.5.7/jquery.fancybox.min.js" ></script>
  <link  rel="stylesheet" href="https://cdn.staticfile.org/fancybox/3.5.7/jquery.fancybox.min.css" />

  <script>
    $('#post img:not(.no-zoom img, img[no-zoom]), img[zoom]').each(
      function () {
        var element = document.createElement('a');
        $(element).attr('data-fancybox', 'images');
        $(element).attr('href', $(this).attr('src'));
        $(this).wrap(element);
      }
    );
  </script>





  

  
    <!-- MathJax -->
    <script>
      MathJax = {
        tex: {
          inlineMath: [['$', '$'], ['\\(', '\\)']]
        },
        options: {
          renderActions: {
            findScript: [10, doc => {
              document.querySelectorAll('script[type^="math/tex"]').forEach(node => {
                const display = !!node.type.match(/; *mode=display/);
                const math = new doc.options.MathItem(node.textContent, doc.inputJax[0], display);
                const text = document.createTextNode('');
                node.parentNode.replaceChild(text, node);
                math.start = { node: text, delim: '', n: 0 };
                math.end = { node: text, delim: '', n: 0 };
                doc.math.push(math);
              });
            }, '', false],
            insertedScript: [200, () => {
              document.querySelectorAll('mjx-container').forEach(node => {
                let target = node.parentNode;
                if (target.nodeName.toLowerCase() === 'li') {
                  target.parentNode.classList.add('has-jax');
                }
              });
            }, '', false]
          }
        }
      };
    </script>

    <script async src="https://cdn.staticfile.org/mathjax/3.0.5/es5/tex-svg.js" ></script>

  











</body>
</html>
